package com.cjack.frenchexcel.logger;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;

/**
 * 切面对象，负责定位到需要进行日志处理的地方
 */
@Aspect
@Component
public class HttpAspect {

    private static final Logger LOG = LoggerFactory.getLogger( HttpAspect.class);

    // 定义切点Pointcut
    @Pointcut("execution(* com.cjack.frenchexcel.appcontroller.*Endpoint.*(..))")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround( ProceedingJoinPoint pjp) throws Throwable {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String queryString = request.getQueryString();
        Object[] args = pjp.getArgs();
        String paramStr = "";
        //获取请求参数集合并进行遍历拼接
        if( args.length > 0){
            if( "POST".equals( method)){
                Object object = args[0];
                JSONObject paramJson = getKeyAndValue( object);
                if( paramJson != null){
                    paramStr = paramJson.toJSONString();
                }
            }else if( "GET".equals( method)){
                paramStr = queryString;
            }
        }
        // result的值就是被拦截方法的返回值
        long start = System.currentTimeMillis();
        Object result = null;
        try{
            result = pjp.proceed();
        }catch (Exception e){
            LOG.error( e.getMessage(), e);
        }

        long end = System.currentTimeMillis();
        LOG.info("-------------------------------start---------------------------------");
        LOG.info("请求地址: " + url);
        LOG.info("请求类型: " + method);
        LOG.info("请求参数: " + paramStr);
        if( result != null){
            if( result instanceof ResponseEntity){
                LOG.info("请求返回值: 文件，不打印到日志");
            }else{
                LOG.info("请求返回值: " + JSONObject.toJSON( result));
            }

        }
        LOG.info("请求耗时: [" + ( end - start) + "]毫秒");
        LOG.info("-------------------------------end-----------------------------------");
        return result;
    }

    public static JSONObject getKeyAndValue(Object obj) {
        JSONObject json = new JSONObject();
        // 得到类对象
        Class userCla = obj.getClass();
        /* 得到类中的所有属性集合 */
        Field[] fs = userCla.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];
            f.setAccessible(true); // 设置些属性是可以访问的
            Object val = new Object();
            try {
                val = f.get(obj);
                // 得到此属性的值
                json.put( f.getName(), val);// 设置键值
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return json;
    }
}
